package org.seckill.service.impl;

import java.util.Date;
import java.util.List;

import org.seckill.dao.SeckillDao;
import org.seckill.dao.SuccessKilledDao;
import org.seckill.dto.Exposer;
import org.seckill.dto.SeckillExecution;
import org.seckill.entity.Seckill;
import org.seckill.entity.SuccessKilled;
import org.seckill.enums.SeckillStatEnum;
import org.seckill.exception.RepeatKillException;
import org.seckill.exception.SeckillCloseException;
import org.seckill.exception.SeckillException;
import org.seckill.service.SeckillService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
@Service
public class SeckillServiceImpl implements SeckillService{
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private SuccessKilledDao successKilledDao;
	@Autowired
	private SeckillDao seckillDao;
	//md5盐值字符串，用于混淆md5
	public final String slat = "dhsaohfwqh79491rwsjfq";

	@Override
	public List<Seckill> getSeckillList() {
		
		return seckillDao.queryAll(0, 4);
	}

	@Override
	public Seckill getById(long seckillId) {
		
		return seckillDao.queryById(seckillId);
	}

	@Override
	public Exposer exportSeckillUrl(long seckillId) {
		Seckill seckill = seckillDao.queryById(seckillId);
		if(seckill == null){
			return new Exposer(false, seckillId);
		}
		Date startTime = seckill.getStartTime();
		Date endTime = seckill.getEndTime();
		Date nowTime = new Date();
		if(nowTime.getTime()<startTime.getTime()||nowTime.getTime()>endTime.getTime()){
			return new Exposer(false, seckillId,nowTime.getTime(),startTime.getTime(),endTime.getTime());
		}
		String md5 = getMD5(seckillId);
		return new Exposer(true, md5, seckillId);
	}
	
	//获取对seckillId进行加密后的md5
	private String getMD5(long seckillId){
		String base = seckillId+"/"+slat;
		String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
		return md5;
	}

	@Override
	@Transactional
	public SeckillExecution executeSeckill(long seckillId, long userPhone,
			String md5) throws SeckillException, SeckillCloseException,
			RepeatKillException {
		if(md5==null|| !md5.equals(getMD5(seckillId))){
			throw new SeckillException("seckill data rewrite");
		}
		
		Date nowTime = new Date();
		
		try {
			//减库存
			int result = seckillDao.reduceNumber(seckillId, nowTime);
			if(result<=0){
				//没有更新到记录，秒杀结束
				throw new SeckillCloseException("seckill is closed");
			}else{
				//记录购买行为插入成功秒杀表
				int insertConut = successKilledDao.insertSuccessKilled(seckillId, userPhone);
				if(insertConut<=0){
					//重复秒杀
					throw new RepeatKillException("重复秒杀");
				}else{
					//秒杀成功
					SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
					return new SeckillExecution(seckillId, SeckillStatEnum.SUCCESS,successKilled);
				}
			}
			
		}catch (SeckillCloseException e1) {
			throw e1;
		}catch(RepeatKillException e2){
			throw e2;
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			//所有编译期异常转化为运行期异常
			throw new SeckillException("seckill error:"+e.getMessage());
		}
		
	}

}
